from invfun import inv, inv_1
from gear import HiddenPrints, PrintToTxt, GearInit, PlanetInit, Gear, PlanetaryGear
from math import sin, cos, tan, radians, degrees, floor, sqrt, acos, atan, pi
import numpy as np
from shichuan_stiff import pt_stiffness
import huichacalc

# 根据太阳轮和内齿轮齿数选择合适的 行星轮齿数
# 输入：太阳轮齿数1，内齿轮齿数2，外啮合副啮合角范围，内啮合副啮合角范围
# 输出：行星轮齿数3

def calcx1(x2, x3, z1, z3, z2, alpha=radians(20)):  # 根据x2,x3，计算两个啮合角，最后计算出x1
    z_segma_13 = z1+z3
    z_segma_32 = z2-z3
    x_segma_32 = x2-x3
    alpha_work_32 = inv_1(
        x_segma_32*2*tan(alpha)/z_segma_32+inv(alpha))
    alpha_work_13 = acos(
        z_segma_13/z_segma_32*cos(alpha_work_32))
    x_segma_13 = z_segma_13 * \
        (inv(alpha_work_13)-inv(alpha))/(2*tan(alpha))
    x1 = x_segma_13 - x3
    return x1

def optz(z1, z2, alpha13range=[23, 27.5], alpha32range=[20, 22]):
    if z1 >= z2:
        raise ValueError('太阳轮齿数过大')

    z3_std = int((z2-z1)/2)

    alpha32r = np.arange(alpha32range[0], alpha32range[1], 0.1)

    #alpha32 = alpha32range[0]

    for dz in range(3):
        z3x = z3_std-dz
        
        z_segma13 = z1 + z3x
        z_segma32 = z2 - z3x
        for alpha32 in alpha32r:
            alpha13 = degrees(acos(z_segma13/z_segma32*cos(radians(alpha32))))
            if (alpha13) >= alpha13range[0] and (alpha13) <= alpha13range[1]:
                return z3x, (alpha13), alpha32

    return z3_std


def optx(m,z1,z3,z2,x2range=np.arange(0,1,0.01),x3range=np.arange(0,1,0.01),alpha=radians(20),ha_std=1,c_std=0.25,k1=10,k2=1):
    pt_objects = []  # 行星齿轮对象列表，用于储存按某种顺序排列的行星齿轮对象，并最后返回
    
    def aim(pt:PlanetaryGear):
        return k1*pt.gear_ac.dyeta + k2*pt.gear_cb.dyeta
    
    for x2 in x2range:
        for x3 in x3range:
            
            try:
                x1 = calcx1(x2, x3, z1, z3, z2, alpha)
                ptInit = PlanetInit(alpha_deg=degrees(alpha),ha_std=ha_std,c_std=c_std)
                pt = PlanetaryGear(m, z1, z3, z2, x1, x3, x2, ptInit,calc=False)
                if (pt.ret_ac and pt.ret_cb): # 满足干涉、齿顶厚等限制条件
                    #dy1 = pt.gear_ac.dyeta
                    #dy2 = pt.gear_cb.dyeta
                    ep1 = pt.gear_ac.ContactRatio
                    ep2 = pt.gear_cb.ContactRatio
                    if ep1 >= 1.3 and ep2 >= 1.3: # 满足基本的重合度条件
                        #_,maxmin = pt_stiffness(pt,xstep=radians(0.01),savefilename='None',show=False)
                        #pt.gear_ac.st_jump_max = maxmin[0][2]
                        #pt.gear_cb.st_jump_max = maxmin[1][2]
                        pt_objects.append(pt)
            except:
                pass

                '''
                if pt.gear_ac.dyeta < 0.1:
                    dy1 = pt.gear_ac.dyeta
                    dy2 = pt.gear_cb.dyeta
                    ep1 = pt.gear_ac.ContactRatio
                    ep2 = pt.gear_cb.ContactRatio
                    print('x1:%.4f,x3:%.3f,x2:%.3f,\tD_Yeta:%.4f,%.4f,\tCRatio:%.4f,%.4f\tA_w:%.3f,%.3f' % (
                        x1, x3, x2, dy1, dy2, ep1, ep2, degrees(pt.gear_ac.alpha_work), degrees(pt.gear_cb.alpha_work)))
                '''
            #pt_objects.sort(key=lambda pt:pt.gear_ac.dyeta)
    pt_objects.sort(key=aim) # 以目标函数进行排序，从小到大
            
    return pt_objects



def aimFun(pt: PlanetaryGear): # 用于排序行星齿轮对象的目标函数
    aim = 10*pt.gear_ac.dyeta + pt.gear_cb.dyeta*0
    return aim




if __name__ == '__main__':
    m = 2
    z1 = 27
    z2 = 108
    z3 = optz(z1,z2)[0]
    print(z3)
    pt_list = optx(m,z1,z3,z2,x2range=np.arange(0,1,0.1),x3range=np.arange(0,1,0.1))
    for i in range(10):
        print(pt_list[i].xa,pt_list[i].xc,pt_list[i].xb,pt_list[i].gear_ac.dyeta,pt_list[i].gear_cb.dyeta,degrees(pt_list[i].gear_ac.alpha_work),degrees(pt_list[i].gear_cb.alpha_work))
    
    
